/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package controllers;

import entities.Event;
import entities.IndoorEvent;
import entities.Invitation;
import entities.OutdoorEvent;
import entities.Place;
import entities.User;
import utils.Weather;
import entities.WeatherForecast;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.logging.Level;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.logging.Logger;
import javax.ejb.Stateful;

/**
 *
 * @author Alberto, Alessandra
 */
@Stateless
public class CalendarManager {
    
    private static final Logger logger = Logger.getLogger("CalendarManager");
    
    @PersistenceContext
    EntityManager em;
    
    @EJB
    UserManager um;
    
    @EJB
    WeatherManager wm;
    
    @EJB
    NotificationManager nm;
    
    public OutdoorEvent createOutdoorEvent (ArrayList<Weather> badweather, String name, Boolean visibility, 
            Integer starthour, Integer startminute, Integer endhour, Integer endminute, Date date, 
            String description, Place place) {
        User user = um.getLoggedUser();
        
        Event event = new OutdoorEvent(wm.getBadWeather(badweather), name, visibility, starthour, startminute, 
                endhour, endminute, date, description, user, place);
        wm.retrieveWeatherForecast((OutdoorEvent)event);
        user.addEvent(event);
        user.addCreatedEvent(event);
        em.persist(event);
        return (OutdoorEvent) event;
    }
    
    public IndoorEvent createIndoorEvent (String name, Boolean visibility, Integer starthour, Integer startminute, 
            Integer endhour, Integer endminute, Date date, String description, Place place) {
        User user = um.getLoggedUser();
        Event event = new IndoorEvent(name, visibility, starthour, startminute, 
                endhour, endminute, date, description, user, place);
        user.addEvent(event);
        user.addCreatedEvent(event);
        em.persist(event);
        return (IndoorEvent) event;
    }
    
    public void modifyEvent (Event event) {
        //Remove all participants except the creator
        Iterator<User> iterpart = event.getParticipants().iterator();
        while (iterpart.hasNext()) {
            User u = iterpart.next();
            if (!u.equals(um.getLoggedUser())) {
                iterpart.remove();
                u.removeEvent(event);
                em.merge(u);
            }
        }
        //Ivitation returns unaccepted
        Iterator<Invitation> iterinv = event.getInvitations().iterator();
        while (iterinv.hasNext()) {
            Invitation inv = iterinv.next();
            inv.setReplied(Boolean.FALSE);
            inv.setVisualized(Boolean.FALSE);
            em.merge(inv);
        }
        //Delete old change notifications
        nm.deleteChangeNotifications(event);
        //Create ChangeNotifications
        nm.createChangeNotifications(event);
        //Retrieve new weather forecast
        if (event instanceof OutdoorEvent) {
            wm.retrieveWeatherForecast((OutdoorEvent)event);
        }
        em.merge(event);
    }
    
    public void deleteEvent (Event event) {
        //Delete all other notifications
        nm.deleteChangeNotifications(event);
        if (event instanceof OutdoorEvent) {
            nm.deleteOneDayNotifications((OutdoorEvent)event);
            nm.deleteThreeDaysNotifications((OutdoorEvent)event);
        }
        //Delete Notification
        nm.createDeleteNotifications(event);
        //Delete Invitations
        ArrayList<Invitation> invitations = new ArrayList<>();
        invitations.addAll(em.createNamedQuery("findByEvent" , Invitation.class)
            .setParameter("Ievent", event)
            .getResultList());
        Iterator<Invitation> iterinv = invitations.iterator();
        while (iterinv.hasNext()) {
            Invitation inv = iterinv.next();
            event.removeInvitation(inv);
            inv.getUser().removeInvitation(inv);
            em.remove(inv);
        }
        //Delete Participants
        Iterator<User> iteruser = event.getParticipants().iterator();
        while (iteruser.hasNext()) {
            User u = iteruser.next();
            iteruser.remove();
            u.removeEvent(event);
            if (u.equals(event.getCreator()))
                u.removeCreatedEvent(event);
            em.merge(u);
        }
        em.merge(event);
    }
    
    public Boolean isCreator (Event event) {
        if (event.getCreator().equals(um.getLoggedUser()))
            return true;
        else return false;
    } 
    
    public ArrayList<Event> listOfEvents () {
        ArrayList<Event> events = new ArrayList<Event>();
        events.addAll(um.getLoggedUser().getEvents());
        
        //Log info
        String s = ((Integer) events.size()).toString();
        logger.log(Level.INFO, "number of events " + s);
        
        return events;
    }
    
}
